1 <!DOCTYPE html PUBLIC
"-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
4 <meta http-equiv=
"Content-Type" content=
"text/html; charset=UTF-8">
5 <meta http-equiv=
"Content-Style-Type" content=
"text/css">
7 <meta name=
"Generator" content=
"Cocoa HTML Writer">
8 <meta name=
"CocoaVersion" content=
"949.54">
9 <style type=
"text/css">
10 p
.p1
{margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Lucida Grande
; min-height: 18.0px}
11 p
.p2
{margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Lucida Grande
}
12 p
.p3
{margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Lucida Grande
; min-height: 15.0px}
13 p
.p4
{margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Lucida Grande
}
14 p
.p5
{margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Lucida Grande
}
15 p
.p6
{margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Lucida Grande
; color: #001fe8}
16 p
.p7
{margin: 0.0px 0.0px 0.0px 0.0px}
17 p
.p8
{margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica
; min-height: 14.0px}
18 p
.p9
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
; color: #0019ba}
19 p
.p10
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
; min-height: 12.0px}
20 p
.p11
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
}
21 p
.p12
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
; color: #ad1d13}
22 p
.p13
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
; color: #606060}
23 span
.s1
{color: #000000}
24 span
.s2
{font: 12.0px Helvetica
}
25 span
.s3
{color: #0019ba}
26 span
.s4
{color: #606060}
27 span
.Apple-tab-span
{white-space:pre
}
31 <p class=
"p1"><br></p>
32 <p class=
"p2"><b>Creating Standalone Applications
</b></p>
33 <p class=
"p3"><br></p>
34 <p class=
"p4"><b>Introduction
</b></p>
35 <p class=
"p3"><br></p>
36 <p class=
"p5">On OS X, applications are special directories known as
"bundles." This allows you to create stand-alone applications running SuperCollider code that are opaque, in the sense that the user does not need to install SuperCollider, run SuperCollider code, or even know that SuperCollider is involved. (Of course, your application must be open-source and comply with the GPL.) This is useful for distributing applications to the general public, or for creating special-purpose applications for your own use.
</p>
37 <p class=
"p3"><br></p>
38 <p class=
"p5">There are two ways of making standalone applications:
<span class=
"Apple-converted-space"> </span></p>
39 <p class=
"p5">A. Modifying an existing
<b>Standalone Template.app
</b> by editing the contents in its folder,
<span class=
"Apple-converted-space"> </span></p>
40 <p class=
"p5"><span class=
"Apple-tab-span"> </span>which can be done without requiring XCode or any other development environments,
<span class=
"Apple-converted-space"> </span></p>
41 <p class=
"p6"><span class=
"s1"><span class=
"Apple-tab-span"> </span>described in
<a href=
"Modifying_Standalones.html"><b>Modifying_Standalones
</b></a>, or
</span></p>
42 <p class=
"p3"><br></p>
43 <p class=
"p5">B. Creating a standalone application from scratch, as described below.
</p>
44 <p class=
"p3"><br></p>
45 <p class=
"p4"><b>Creating a standalone application
</b></p>
46 <p class=
"p3"><br></p>
47 <p class=
"p5">1- Obtain a copy of the SuperCollider source code. The easiest way to do so is to download the latest source release from SourceForge:
</p>
48 <p class=
"p5">http://sourceforge.net/projects/supercollider/
</p>
49 <p class=
"p3"><br></p>
50 <p class=
"p5">2- Open the Language.xcodeproj project in Xcode.
</p>
51 <p class=
"p3"><br></p>
52 <p class=
"p5">3- Rename the
"Standalone Template" target by control-clicking it and choosing
"Rename". This target name is used for both the .app name and for the name presented in the menu bar.
</p>
53 <p class=
"p3"><br></p>
54 <p class=
"p7"><span class=
"s2"><img src=
"attachments/Creating-Standalone-Applications/Pasted Graphic 1.png" alt=
"attachments/Creating-Standalone-Applications/Pasted Graphic 1.png"></span></p>
55 <p class=
"p8"><br></p>
56 <p class=
"p5">4- Customize the
"Standalone Resources" directory, which is located at the root of the SuperCollider source directory. Any files you put in this directory will overide the files placed in the standalone application. For example if you wanted to create your own version of Array.sc you would need to create the following path (creating folders where necessary):
<span class=
"Apple-converted-space"> </span></p>
57 <p class=
"p5"><span class=
"Apple-tab-span"> </span>Standalone Resources/SCClassLibrary/Common/Collections/Array.sc
</p>
58 <p class=
"p3"><span class=
"Apple-tab-span"> </span></p>
59 <p class=
"p5">Your version of Array.sc will now overide the default. Similarly you can replace application resources to customize your application.
"Standalone Resources/SCcube.icns" can be overridden to provide a custom icon.
"Standalone Resources/English.lproj/MainMenu.nib" can be overriden to provide a custom menu bar and
"Standalone Resources/English.lproj/Credits.rtf" can be overidden to provide a new about box. The
"Standalone Resources" directory by default comes with a small demo application that puts up a window with a button that generates a tone when pushed.
</p>
60 <p class=
"p3"><br></p>
61 <p class=
"p5">5- Build the standalone application by control-clicking on the target and choosing
"Build [target name]". This will place your standalone app in the build directory. It is recommended that you develop your application fully in a normal SuperCollider environment before creating a standalone application.
</p>
62 <p class=
"p3"><br></p>
63 <p class=
"p7"><span class=
"s2"><img src=
"attachments/Creating-Standalone-Applications/Pasted Graphic 2.png" alt=
"attachments/Creating-Standalone-Applications/Pasted Graphic 2.png"></span></p>
64 <p class=
"p3"><br></p>
65 <p class=
"p4"><b>Adding your own behavior
</b></p>
66 <p class=
"p3"><br></p>
67 <p class=
"p5">You've now created an application that behaves exactly like SuperCollider. To run your own code on launch and simulate an ordinary application, you'll need to modify the startup-related methods, which are overwritten in (Standalone Resources)/SCClassLibrary/modifyStartup.sc.
<span class=
"Apple-converted-space"> </span></p>
68 <p class=
"p3"><br></p>
69 <p class=
"p5">Here's an example (the same code used by the SC_StandAlone target):
</p>
70 <p class=
"p3"><br></p>
71 <p class=
"p9"><span class=
"s1">+
</span>OSXPlatform
<span class=
"s1"> {
</span></p>
72 <p class=
"p10"><br></p>
73 <p class=
"p11"><span class=
"Apple-tab-span"> </span>startupFiles {
</p>
74 <p class=
"p12">//
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>var filename =
"startup.rtf";
</p>
75 <p class=
"p12">//
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>^[this.systemAppSupportDir +/+ filename, this.userAppSupportDir +/+ filename];
</p>
76 <p class=
"p12"><span class=
"s1"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// look for startup files inside the app Contents directory
</p>
77 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s3">var
</span> filename =
<span class=
"s4">"startup.*"</span>;
</p>
78 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>^(
<span class=
"s3">String
</span>.scDir +/+ filename).pathMatch;
</p>
79 <p class=
"p11"><span class=
"Apple-tab-span"> </span>}
</p>
80 <p class=
"p10"><span class=
"Apple-tab-span"> </span></p>
81 <p class=
"p11"><span class=
"Apple-tab-span"> </span>startup {
</p>
82 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s3">Document
</span>.implementationClass.startup;
</p>
83 <p class=
"p12"><span class=
"s1"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// make a server window for the internal if you like
</p>
84 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s3">Server
</span>.internal.makeWindow;
</p>
85 <p class=
"p12">//
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>Server.local.makeWindow;
</p>
86 <p class=
"p12"><span class=
"s1"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// uncomment if you use a startup file
</p>
87 <p class=
"p12">//
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>this.loadStartupFiles;
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></p>
88 <p class=
"p12"><span class=
"s1"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// uncomment if you have multiple help files
</p>
89 <p class=
"p12">//
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>Help.addToMenu;
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></p>
90 <p class=
"p11"><span class=
"Apple-tab-span"> </span>}
</p>
92 <p class=
"p10"><br></p>
93 <p class=
"p11">+
<span class=
"s3">Main
</span> {
<span class=
"Apple-converted-space"> </span></p>
94 <p class=
"p11"><span class=
"Apple-tab-span"> </span>startup {
</p>
95 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>platform =
<span class=
"s3">this
</span>.platformClass.new;
</p>
96 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>platform.initPlatform;
</p>
97 <p class=
"p10"><span class=
"Apple-tab-span"> </span></p>
98 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s3">super
</span>.startup;
</p>
99 <p class=
"p10"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></p>
100 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s3">GUI
</span>.fromID(
<span class=
"s3">this
</span>.platform.defaultGUIScheme );
</p>
101 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s3">GeneralHID
</span>.fromID(
<span class=
"s3">this
</span>.platform.defaultHIDScheme );
</p>
102 <p class=
"p10"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></p>
103 <p class=
"p12"><span class=
"s1"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// Set Server.default and the 's' interpreter variable to the internal server.
</p>
104 <p class=
"p12"><span class=
"s1"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// You should use the internal server for standalone applications --
</p>
105 <p class=
"p12"><span class=
"s1"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// otherwise, if your application has a problem, the user will
</p>
106 <p class=
"p12"><span class=
"s1"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// be stuck with a process, possibly making sound, that he won't know
<span class=
"Apple-converted-space"> </span></p>
107 <p class=
"p12"><span class=
"s1"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// how to kill.
</p>
108 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s3">Server
</span>.default =
<span class=
"s3">Server
</span>.internal;
<span class=
"Apple-converted-space"> </span></p>
109 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>interpreter.s =
<span class=
"s3">Server
</span>.default;
</p>
110 <p class=
"p10"><br></p>
111 <p class=
"p12"><span class=
"s1"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// some folder paths that should point inside the app's Contents folder
</p>
112 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s3">SynthDef
</span>.synthDefDir =
<span class=
"s3">String
</span>.scDir +/+
<span class=
"s4">"synthdefs/"</span>;
</p>
113 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s3">Archive
</span>.archiveDir =
<span class=
"s3">String
</span>.scDir;
</p>
114 <p class=
"p10"><br></p>
115 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s3">this
</span>.platform.startup;
</p>
116 <p class=
"p10"><br></p>
117 <p class=
"p12"><span class=
"s1"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// from here on, you should customize what should happen...
</p>
118 <p class=
"p10"><br></p>
119 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s3">StartUp
</span>.run;
</p>
120 <p class=
"p10"><br></p>
121 <p class=
"p12"><span class=
"s1"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// One can boot the server, then use .load to evaluate a file
</p>
122 <p class=
"p12"><span class=
"s1"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// OR - put things into a class... like the SCSA_Demo
</p>
123 <p class=
"p10"><br></p>
124 <p class=
"p13"><span class=
"s1"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>"Welcome to Standalone Demo made with SuperCollider, type cmd-d for help."<span class=
"s1">.postln;
</span></p>
125 <p class=
"p10"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></p>
126 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s3">Server
</span>.default.boot;
</p>
127 <p class=
"p10"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></p>
128 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s3">Server
</span>.default.waitForBoot({
</p>
129 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s3">SCSA_Demo
</span>.new(
<span class=
"s4">"The Cheese Stands Alone"</span>,
<span class=
"s3">Rect
</span>(
400,
400,
300,
200), interpreter.s).front;
</p>
130 <p class=
"p12">//
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>(String.scDir.dirname ++
"/MFBSD.rtf").load;
</p>
131 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>});
</p>
132 <p class=
"p11"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>// close post window if user should not have it
</p>
133 <p class=
"p11">//
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>Document.listener.close
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></p>
134 <p class=
"p11"><span class=
"Apple-tab-span"> </span>}
</p>
135 <p class=
"p10"><span class=
"Apple-tab-span"> </span></p>
137 <p class=
"p3"><br></p>
138 <p class=
"p5">The class SCSA_Demo contains the entire application, including the main window. This is the tidiest way to work, and requires the least modification to SuperCollider. If you don't want to write a class, you can execute an .rtf file instead:
</p>
139 <p class=
"p3"><br></p>
140 <p class=
"p5">load(String.scDir ++
"/myapp.rtf");
</p>
141 <p class=
"p3"><br></p>
142 <p class=
"p5">However, any sizable application will benefit from encapsulation in classes.
</p>
143 <p class=
"p3"><br></p>
144 <p class=
"p5">Note that the example uses the internal server. This is part and parcel of keeping the application stand-alone; it shouldn't call extraneous processes behind the user's back that will persist if the application fails. If you need to use the local server for some reason, make sure scsynth is in your resources folder.
</p>
145 <p class=
"p3"><br></p>
146 <p class=
"p4"><b>Managing multiple standalone applications
</b></p>
147 <p class=
"p3"><br></p>
148 <p class=
"p5">To manage several standalone applications simply create several targets and several resources directories. The resources directories should be named according to
"[target name] Resources". If a resources directory is found when building that matches the target name, that directory will be used instead than the default
"Standalone Resources" directory.
</p>